home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / mac / MAC / Programming Stuff / Sample Code / Mixed Bag / Sample Components / SGChannelPict.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  21.1 KB  |  769 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        SGChannelPict.r
  3.  
  4.     Written by:    Peter Hoddie
  5.  
  6.     Copyright:    © 1992 by Apple Computer, Inc., all rights reserved.
  7.  
  8. */
  9.  
  10. #include <Errors.h>
  11. #include <Memory.h>
  12. #include <OSUtils.h>
  13. #include <Packages.h>
  14. #include <QuickDraw.h>
  15. #include <Resources.h>
  16.  
  17. #include <QuickTimeComponents.h>
  18.  
  19. #define kMediaTimeScale 600
  20.  
  21. typedef struct {
  22.     ComponentInstance        self;
  23.     SeqGrabComponent        grabber;
  24.  
  25.     long                    usage;
  26.     Boolean                    paused;
  27.  
  28.     CGrafPtr                destPort;
  29.     GDHandle                destGD;
  30.  
  31.     CGrafPtr                tempPort;
  32.  
  33.     MatrixRecord            displayMatrix;
  34.     Rect                    destRect;
  35.  
  36.     Rect                    srcRect;
  37.  
  38.     RgnHandle                clip;
  39.  
  40.     Boolean                    inPreview;
  41.     Boolean                    inRecord;
  42.  
  43.     TimeBase                base;
  44.  
  45.     long                    bytesWritten;
  46.  
  47.     Boolean                    showTickCount;
  48.  
  49.     long                    saveUsage;
  50. } SGPictGlobalsRecord, *SGPictGlobals;
  51.  
  52. pascal ComponentResult SGPictOpen (SGPictGlobals store, ComponentInstance self);
  53. pascal ComponentResult SGPictClose (SGPictGlobals store, ComponentInstance self);
  54. pascal ComponentResult SGPictCanDo (SGPictGlobals store, short ftnNumber );
  55. pascal ComponentResult SGPictVersion (SGPictGlobals store);
  56.  
  57. pascal ComponentResult SGPictSetGWorld (SGPictGlobals store, CGrafPtr gp, GDHandle gd);
  58. pascal ComponentResult SGPictSetChannelUsage (SGPictGlobals store, long usage);
  59. pascal ComponentResult SGPictGetChannelUsage (SGPictGlobals store, long *usage);
  60. pascal ComponentResult SGPictGetChannelInfo (SGPictGlobals store, long *channelInfo);
  61.  
  62. pascal ComponentResult SGPictSetChannelMatrix (SGPictGlobals store, const MatrixRecord *m);
  63. pascal ComponentResult SGPictGetChannelMatrix (SGPictGlobals store, MatrixRecord *m);
  64. pascal ComponentResult SGPictSetChannelBounds (SGPictGlobals store, const Rect *bounds);
  65. pascal ComponentResult SGPictGetChannelBounds (SGPictGlobals store, Rect *bounds);
  66. pascal ComponentResult SGPictSetChannelClip (SGPictGlobals store, RgnHandle theClip);
  67. pascal ComponentResult SGPictGetChannelClip (SGPictGlobals store, RgnHandle *theClip);
  68.  
  69. pascal ComponentResult SGPictStartPreview (SGPictGlobals store);
  70. pascal ComponentResult SGPictStartRecord (SGPictGlobals store);
  71. pascal ComponentResult SGPictIdle (SGPictGlobals store);
  72. pascal ComponentResult SGPictStop (SGPictGlobals store);
  73. pascal ComponentResult SGPictPause (SGPictGlobals store, Byte pause);
  74. pascal ComponentResult SGPictPrepare (SGPictGlobals store, Boolean prepareForPreview, 
  75.                 Boolean prepareForRecord);
  76. pascal ComponentResult SGPictRelease (SGPictGlobals store);
  77.  
  78. pascal ComponentResult SGPictGetChannelSampleDescription (SGPictGlobals store, Handle sampleDesc);
  79. pascal ComponentResult SGPictGetChannelDeviceList (SGPictGlobals store, long selectionFlags, 
  80.                 SGDeviceList *list);
  81. pascal ComponentResult SGPictSetChannelDevice (SGPictGlobals store, StringPtr name);
  82. pascal ComponentResult SGPictGetChannelTimeScale (SGPictGlobals store, TimeScale *scale);
  83. pascal ComponentResult SGPictInitChannel (SGPictGlobals store, SeqGrabComponent owner);
  84. pascal ComponentResult SGPictWriteSamples (SGPictGlobals store, Movie m, AliasHandle theFile);
  85. pascal ComponentResult SGPictGetDataRate (SGPictGlobals store, long *bytesPerSecond);
  86.  
  87. pascal ComponentResult SGPictPanelGetDitl (SGPictGlobals store, Handle *ditl);
  88. pascal ComponentResult SGPictPanelInstall (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset);
  89. pascal ComponentResult SGPictPanelEvent (SGPictGlobals store, SGChannel c, DialogPtr d, 
  90.                 short itemOffset, EventRecord *theEvent, short *itemHit, Boolean *handled);
  91. pascal ComponentResult SGPictPanelRemove (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset);
  92. pascal ComponentResult SGPictPanelGetSettings (SGPictGlobals store, SGChannel c, UserData *ud, long flags);
  93. pascal ComponentResult SGPictPanelSetSettings (SGPictGlobals store, SGChannel c, UserData ud, long flags);
  94.  
  95. pascal ComponentResult SGPictSetShowTickCount (SGPictGlobals store, Boolean show);
  96. pascal ComponentResult SGPictGetShowTickCount (SGPictGlobals store, Boolean *show);
  97.  
  98. pascal ComponentResult SGPICTDispatcher(ComponentParameters *params, Handle storage);
  99.  
  100. /************************
  101.     Component Management
  102. ************************/
  103.  
  104. pascal ComponentResult SGPICTDispatcher(ComponentParameters *params, Handle storage)
  105. {
  106.     OSErr err = badComponentSelector;
  107.     ComponentFunction componentProc = 0;
  108.  
  109.     switch (params->what) {
  110.         case kComponentOpenSelect: componentProc = SGPictOpen; break;
  111.         case kComponentCloseSelect: componentProc = SGPictClose; break;
  112.         case kComponentCanDoSelect: componentProc = SGPictCanDo; break;
  113.         case kComponentVersionSelect: componentProc = SGPictVersion; break;
  114.  
  115.         case kSGSetGWorldSelect: componentProc = SGPictSetGWorld; break;
  116.  
  117.         case kSGStartPreviewSelect: componentProc = SGPictStartPreview; break;
  118.         case kSGStartRecordSelect: componentProc = SGPictStartRecord; break;
  119.         case kSGIdleSelect: componentProc = SGPictIdle; break;
  120.         case kSGStopSelect: componentProc = SGPictStop; break;
  121.         case kSGPauseSelect: componentProc = SGPictPause; break;
  122.         case kSGPrepareSelect: componentProc = SGPictPrepare; break;
  123.         case kSGReleaseSelect: componentProc = SGPictRelease; break;
  124.  
  125.         case kSGCSetChannelUsageSelect: componentProc = SGPictSetChannelUsage; break;
  126.         case kSGCGetChannelUsageSelect: componentProc = SGPictGetChannelUsage; break;
  127.         case kSGCSetChannelBoundsSelect: componentProc = SGPictSetChannelBounds; break;
  128.         case kSGCGetChannelBoundsSelect: componentProc = SGPictGetChannelBounds; break;
  129.         case kSGCGetChannelInfoSelect: componentProc = SGPictGetChannelInfo; break;
  130.  
  131.         case kSGCSetChannelMatrixSelect: componentProc = SGPictSetChannelMatrix; break;
  132.         case kSGCGetChannelMatrixSelect: componentProc = SGPictGetChannelMatrix; break;
  133.         case kSGCSetChannelClipSelect: componentProc = SGPictSetChannelClip; break;
  134.         case kSGCGetChannelClipSelect: componentProc = SGPictGetChannelClip; break;
  135.  
  136.         case kSGCGetChannelSampleDescriptionSelect: componentProc = SGPictGetChannelSampleDescription; break;
  137.         case kSGCGetChannelDeviceListSelect: componentProc = SGPictGetChannelDeviceList; break;
  138.         case kSGCSetChannelDeviceSelect: componentProc = SGPictSetChannelDevice; break;
  139.         case kSGCGetChannelTimeScaleSelect: componentProc = SGPictGetChannelTimeScale; break;
  140.  
  141.         case kSGCInitChannelSelect: componentProc = SGPictInitChannel; break;
  142.         case kSGCWriteSamplesSelect: componentProc = SGPictWriteSamples; break;
  143.         case kSGCGetDataRateSelect: componentProc = SGPictGetDataRate; break;
  144.  
  145.         case kSGCPanelGetDitlSelect: componentProc = SGPictPanelGetDitl; break;
  146.         case kSGCPanelInstallSelect: componentProc = SGPictPanelInstall; break;
  147.         case kSGCPanelEventSelect: componentProc = SGPictPanelEvent; break;
  148.         case kSGCPanelRemoveSelect: componentProc = SGPictPanelRemove; break;
  149.         case kSGCPanelGetSettingsSelect: componentProc = SGPictPanelGetSettings; break;
  150.         case kSGCPanelSetSettingsSelect: componentProc = SGPictPanelSetSettings; break;
  151.  
  152.         // Private component calls
  153.         case 0x0100: componentProc = SGPictSetShowTickCount ;break;
  154.         case 0x0101: componentProc = SGPictGetShowTickCount ;break;
  155.     }
  156.  
  157.     if (componentProc)
  158.         err = CallComponentFunctionWithStorage(storage, params, componentProc);
  159.  
  160.     return err;
  161. }
  162.  
  163. pascal ComponentResult SGPictCanDo (SGPictGlobals store, short ftnNumber )
  164. {
  165.     switch (ftnNumber) {
  166.         case kComponentOpenSelect:
  167.         case kComponentCloseSelect:
  168.         case kComponentCanDoSelect:
  169.         case kComponentVersionSelect:
  170.         
  171.         case kSGSetGWorldSelect: 
  172.  
  173.         case kSGStartPreviewSelect:
  174.         case kSGStartRecordSelect: 
  175.         case kSGIdleSelect: 
  176.         case kSGStopSelect: 
  177.         case kSGPauseSelect: 
  178.         case kSGPrepareSelect: 
  179.         case kSGReleaseSelect: 
  180.  
  181.         case kSGCSetChannelUsageSelect: 
  182.         case kSGCGetChannelUsageSelect: 
  183.         case kSGCSetChannelBoundsSelect: 
  184.         case kSGCGetChannelBoundsSelect: 
  185.         case kSGCGetChannelInfoSelect: 
  186.  
  187.         case kSGCSetChannelMatrixSelect: 
  188.         case kSGCGetChannelMatrixSelect: 
  189.         case kSGCSetChannelClipSelect: 
  190.         case kSGCGetChannelClipSelect: 
  191.  
  192.         case kSGCGetChannelSampleDescriptionSelect: 
  193.         case kSGCGetChannelDeviceListSelect: 
  194.         case kSGCSetChannelDeviceSelect: 
  195.         case kSGCGetChannelTimeScaleSelect: 
  196.  
  197.         case kSGCInitChannelSelect: 
  198.         case kSGCWriteSamplesSelect: 
  199.         case kSGCGetDataRateSelect: 
  200.  
  201.         case kSGCPanelGetDitlSelect: 
  202.         case kSGCPanelInstallSelect: 
  203.         case kSGCPanelEventSelect: 
  204.         case kSGCPanelRemoveSelect: 
  205.         case kSGCPanelGetSettingsSelect: 
  206.         case kSGCPanelSetSettingsSelect: 
  207.  
  208.         // Private component calls
  209.         case 0x0100: 
  210.         case 0x0101: 
  211.             return true;
  212.         default:
  213.             return false;
  214.     }
  215. }
  216.  
  217. pascal ComponentResult SGPictVersion (SGPictGlobals store)
  218. {
  219.     return 0x00020001;
  220. }
  221.  
  222. pascal ComponentResult SGPictOpen (SGPictGlobals store, ComponentInstance self)
  223. {
  224.     OSErr err;
  225.     Rect r;
  226.     CGrafPtr tempPort;
  227.     GrafPtr savePort;
  228.  
  229.     // allocate globals
  230.     store = (SGPictGlobals)NewPtrClear(sizeof(SGPictGlobalsRecord));
  231.     if (err = MemError()) goto bail;
  232.  
  233.     // create a temporary port for drawing to in the idle routine
  234.     tempPort = (CGrafPtr)NewPtr(sizeof(CGrafPort));
  235.     if (err = MemError()) {
  236.         DisposePtr((Ptr)store);
  237.         goto bail;
  238.     }
  239.     GetPort(&savePort);
  240.     OpenCPort(tempPort);
  241.     SetPort((GrafPtr)tempPort);
  242.     PortSize(4096, 4096);        // randomly big port
  243.     SetRect(&r, 0, 0, 4096, 4096);
  244.     RectRgn(tempPort->visRgn, &r);
  245.     ClipRect(&r);
  246.     SetPort(savePort);
  247.  
  248.     store->self = self;
  249.     store->tempPort = tempPort;
  250.     store->showTickCount = false;
  251.     SetComponentInstanceStorage(self, (Handle)store);
  252.  
  253. bail:
  254.     return err;
  255. }
  256.  
  257. pascal ComponentResult SGPictClose (SGPictGlobals store, ComponentInstance self)
  258. {
  259.     if (store) {
  260.         if (store->clip) DisposeRgn(store->clip);
  261.         if (store->tempPort) {
  262.             CloseCPort(store->tempPort);
  263.             DisposePtr((Ptr)store->tempPort);
  264.         }
  265.         DisposPtr((Ptr)store);
  266.     }
  267.  
  268.     return noErr;
  269. }
  270.  
  271. /************************
  272.     Required SG Channel Calls
  273. ************************/
  274.  
  275. pascal ComponentResult SGPictSetGWorld (SGPictGlobals store, CGrafPtr gp, GDHandle gd)
  276. {
  277. // remember the destination GWorld
  278.     store->destPort = gp;
  279.     store->destGD = gd;
  280.  
  281.     return noErr;
  282. }
  283.  
  284. pascal ComponentResult SGPictSetChannelUsage (SGPictGlobals store, long usage)
  285. {
  286.     store->usage = usage;
  287.  
  288.     return noErr;
  289. }
  290.  
  291. pascal ComponentResult SGPictGetChannelUsage (SGPictGlobals store, long *usage)
  292. {
  293.     *usage = store->usage;
  294.  
  295.     return noErr;
  296. }
  297.  
  298. pascal ComponentResult SGPictGetChannelInfo (SGPictGlobals store, long *channelInfo)
  299. {
  300.     *channelInfo = seqGrabHasBounds;
  301.  
  302.     return noErr;
  303. }
  304.  
  305. pascal ComponentResult SGPictSetChannelMatrix (SGPictGlobals store, const MatrixRecord *m)
  306. {
  307.     OSErr err = noErr;
  308.     MatrixRecord mat;
  309.     short matType;
  310.  
  311.     // determine the matrix being set
  312.     if (m)
  313.         mat = *m;
  314.     else
  315.         SetIdentityMatrix(&mat);
  316.  
  317.     // validate it
  318.     matType = GetMatrixType(&mat);
  319.     if ((mat.matrix[0][0] < 0) || (mat.matrix[1][1] < 0) || (matType >= linearMatrixType))
  320.         return paramErr;
  321.  
  322.     // update the matrix and destination rect
  323.     store->displayMatrix = mat;
  324.     store->destRect = store->srcRect;
  325.     TransformRect(&mat, &store->destRect, nil);
  326.  
  327.     return err;
  328. }
  329.  
  330. pascal ComponentResult SGPictGetChannelMatrix (SGPictGlobals store, MatrixRecord *m)
  331. {
  332.     *m = store->displayMatrix;
  333.  
  334.     return noErr;
  335. }
  336.  
  337. pascal ComponentResult SGPictSetChannelBounds (SGPictGlobals store, const Rect *bounds)
  338. {
  339.     // remember destination rect
  340.     store->destRect = *bounds;
  341.     // recalculate display matrix from it
  342.     RectMatrix(&store->displayMatrix, &store->srcRect, &store->destRect);
  343.  
  344.     return noErr;
  345. }
  346.  
  347. pascal ComponentResult SGPictGetChannelBounds (SGPictGlobals store, Rect *bounds)
  348. {
  349.     *bounds = store->destRect;
  350.  
  351.     return noErr;
  352. }
  353.  
  354. pascal ComponentResult SGPictSetChannelClip (SGPictGlobals store, RgnHandle theClip)
  355. {
  356.     OSErr err = noErr;
  357.  
  358.     if (store->clip) {
  359.         DisposeRgn(store->clip);
  360.         store->clip = nil;
  361.     }
  362.     if (theClip) {
  363.         err = HandToHand((Handle *)&theClip);
  364.         store->clip = theClip;
  365.     }
  366.  
  367.     return err;
  368. }
  369.  
  370. pascal ComponentResult SGPictGetChannelClip (SGPictGlobals store, RgnHandle *theClip)
  371. {
  372.     OSErr err = noErr;
  373.  
  374.     if (*theClip = store->clip)
  375.         err = HandToHand((Handle *)theClip);
  376.  
  377.     return err;
  378. }
  379.  
  380. pascal ComponentResult SGPictStartPreview (SGPictGlobals store)
  381. {
  382.     store->inPreview = (store->usage & seqGrabPreview) != 0;
  383.     return noErr;
  384. }
  385.  
  386. pascal ComponentResult SGPictStartRecord (SGPictGlobals store)
  387. {
  388.     store->inRecord = (store->usage & seqGrabRecord) != 0;
  389.     store->inPreview = (store->usage & seqGrabPlayDuringRecord) != 0;
  390.     return noErr;
  391. }
  392.  
  393. pascal ComponentResult SGPictIdle (SGPictGlobals store)
  394. {
  395.     OSErr err = noErr;
  396.  
  397.     if (!store->paused && (store->inRecord || store->inPreview)) {
  398.         Point mouseLoc;
  399.         Rect r;
  400.         PicHandle tempPict = nil;
  401.         TimeRecord tr;
  402.         CGrafPtr savePort;
  403.         GDHandle saveGD;
  404.         Rect maxR;
  405.     
  406.         GetGWorld(&savePort, &saveGD);
  407.  
  408.         GetTimeBaseTime(store->base, kMediaTimeScale, &tr);    
  409.         
  410.         // figure the current area around the mouse (only on main screen)
  411.         SetGWorld(store->tempPort, GetMainDevice());
  412.         GetMouse(&mouseLoc);
  413.         LocalToGlobal(&mouseLoc);
  414.         r.top = r.bottom = mouseLoc.v;
  415.         r.left = r.right = mouseLoc.h;
  416.         InsetRect(&r, -(store->srcRect.right >> 1), -(store->srcRect.bottom >> 1));
  417.         maxR = (**GetMainDevice()).gdRect;
  418.         if (r.left < maxR.left) OffsetRect(&r, -r.left + maxR.left, 0);
  419.         if (r.top < maxR.top) OffsetRect(&r, 0, -r.top + maxR.top);
  420.         if (r.right > maxR.right) OffsetRect(&r, maxR.right - r.right, 0);
  421.         if (r.bottom > maxR.bottom) OffsetRect(&r, 0, maxR.bottom - r.bottom);
  422.  
  423.         // copy the screen into a picture
  424.         tempPict = OpenPicture(&r);
  425.             CopyBits((BitMap *)&store->tempPort->portPixMap, 
  426.                         (BitMap *)&store->tempPort->portPixMap, &r, &r, srcCopy, nil);
  427.             if (store->showTickCount) {
  428.                 // if they want to see ticks, draw them
  429.                 Str63 str;
  430.  
  431.                 NumToString(TickCount(), str);
  432.                 r.right = r.left + StringWidth(str) + 4; // do some magic positioning
  433.                 r.bottom = r.top + 14;
  434.                 EraseRect(&r);
  435.                 MoveTo(r.left + 2, r.bottom - 3);
  436.                 TextSize(12);
  437.                 DrawString(str);
  438.             }
  439.  
  440.         ClosePicture();
  441.  
  442.         // if recording, add data to movie
  443.         if (store->inRecord) {
  444.             long offset;
  445.             long pictSize = GetHandleSize((Handle)tempPict);
  446.  
  447.             HLock((Handle)tempPict);
  448.             err = SGAddMovieData(store->grabber, store->self, 
  449.                         (Ptr)*tempPict, pictSize, &offset, 0, tr.value.lo, seqGrabWriteAppend);
  450.             store->bytesWritten += pictSize;
  451.         }
  452.  
  453.         // if we need to show the preview image, do that
  454.         if (store->inPreview) {
  455.             RgnHandle saveClip;
  456.  
  457.             SetGWorld(store->destPort, store->destGD);
  458.             if (store->clip) {
  459.                 saveClip = NewRgn();
  460.                 GetClip(saveClip);
  461.                 SetClip(store->clip);
  462.             }
  463.             DrawPicture(tempPict, &store->destRect);
  464.             if (store->clip) {
  465.                 SetClip(saveClip);
  466.                 DisposeRgn(saveClip);
  467.             }
  468.         }
  469.  
  470.         KillPicture(tempPict);
  471.  
  472.         SetGWorld(savePort, saveGD);
  473.     }
  474.  
  475.     return err;
  476. }
  477.  
  478. pascal ComponentResult SGPictStop (SGPictGlobals store)
  479. {
  480.     store->inRecord = store->inPreview = false;
  481.  
  482.     return noErr;
  483. }
  484.  
  485. pascal ComponentResult SGPictPause (SGPictGlobals store, Byte pause)
  486. {
  487.     store->paused = pause;
  488.  
  489.     return noErr;
  490. }
  491.  
  492. pascal ComponentResult SGPictPrepare (SGPictGlobals store, Boolean prepareForPreview, Boolean prepareForRecord)
  493. {
  494.     store->bytesWritten = 0;
  495.  
  496.     return noErr;
  497. }
  498.  
  499. pascal ComponentResult SGPictRelease (SGPictGlobals store)
  500. {
  501.     return noErr;
  502. }
  503.  
  504. pascal ComponentResult SGPictGetChannelSampleDescription (SGPictGlobals store, Handle sampleDesc)
  505. {
  506.     OSErr err;
  507.     SampleDescriptionPtr sdp;
  508.  
  509.     SetHandleSize(sampleDesc, sizeof(SampleDescription));
  510.     if (err = MemError()) goto bail;
  511.  
  512.     // make up a minimal sample description
  513.     sdp = (SampleDescriptionPtr)*sampleDesc;
  514.     sdp->descSize = sizeof(SampleDescription);
  515.     sdp->dataFormat = 'PICT';
  516.     sdp->resvd1 = 0;
  517.     sdp->resvd2 = 0;
  518.     sdp->dataRefIndex = 0;
  519.  
  520. bail:
  521.     return err;
  522. }
  523.  
  524. pascal ComponentResult SGPictGetChannelDeviceList (SGPictGlobals store, long selectionFlags, SGDeviceList *list)
  525. {
  526.     *list = (SGDeviceList)NewHandleClear(sizeof(SGDeviceListRecord));        // no devices
  527.  
  528.     return MemError();
  529. }
  530.  
  531. pascal ComponentResult SGPictSetChannelDevice (SGPictGlobals store, StringPtr name)
  532. {
  533.     return noErr;
  534. }
  535.  
  536. pascal ComponentResult SGPictGetChannelTimeScale (SGPictGlobals store, TimeScale *scale)
  537. {
  538.     *scale = kMediaTimeScale;
  539.  
  540.     return noErr;
  541. }
  542.  
  543. pascal ComponentResult SGPictInitChannel (SGPictGlobals store, SeqGrabComponent owner)
  544. {
  545.     // initialize any variable here
  546.     SetRect(&store->srcRect, 0, 0, 160, 120);     // size around mouse that we capture
  547.     SetIdentityMatrix(&store->displayMatrix);
  548.  
  549.     store->grabber = owner;
  550.     SGGetTimeBase(owner, &store->base);
  551.  
  552.     return noErr;
  553. }
  554.  
  555. pascal ComponentResult SGPictWriteSamples (SGPictGlobals store, Movie m, AliasHandle theFile)
  556. {
  557.     OSErr err = 0;
  558.     Track pictT;
  559.     Media pictM;
  560.     long i;
  561.     MatrixRecord aMatrix;
  562.     Rect from, to;
  563.     seqGrabFrameInfo fi;
  564.     TimeRecord tr;
  565.     TimeValue mediaDuration;
  566.     SampleDescriptionHandle sampleDesc = 0;
  567.  
  568.     if (!(store->usage & seqGrabRecord))
  569.         return err;
  570.  
  571.     sampleDesc = (SampleDescriptionHandle)NewHandle(4);
  572.     if (err = MemError()) goto bail;
  573.     if (err = SGGetChannelSampleDescription(store->self, (Handle)sampleDesc)) goto bail;
  574.  
  575.     SetRect(&from, 0, 0, store->srcRect.right, store->srcRect.bottom);
  576.     to = from;
  577.     TransformRect(&store->displayMatrix, &to, nil);
  578.  
  579.     pictT = NewMovieTrack(m, (long)from.right << 16, (long)from.bottom << 16, 0);
  580.     pictM = NewTrackMedia(pictT, 'PICT', kMediaTimeScale, (Handle)theFile, rAliasType);
  581.  
  582.     fi.frameChannel = store->self;
  583.     i = -1;
  584.     do {
  585.         TimeValue frameDuration;
  586.  
  587.         err = SGGetNextFrameReference(store->grabber, &fi, &frameDuration, &i);
  588.         if (err) {
  589.             if (err == paramErr)
  590.                 err = 0;
  591.             break;
  592.         }
  593.  
  594.         err = AddMediaSampleReference(pictM, 
  595.                 fi.frameOffset, fi.frameSize,
  596.                 frameDuration,
  597.                 sampleDesc, 1,
  598.                 0, 0);
  599.  
  600.         if (err == invalidDuration) {
  601.             err = noErr;
  602.             break;
  603.         }
  604.     } while (!err);
  605.  
  606. done:
  607.     if (err) goto bail;
  608.  
  609.     GetTimeBaseTime(store->base, 0, &tr);
  610.     ConvertTimeScale(&tr, kMediaTimeScale);        // trim media inserted to not extend beyond end time
  611.     mediaDuration = GetMediaDuration(pictM);
  612.     if (tr.value.lo > mediaDuration)
  613.         tr.value.lo = mediaDuration;        // this should never happen, 
  614.                                     // but avoiding an error at this step seems like a good idea
  615.     err = InsertMediaIntoTrack(pictT, 0, 0, tr.value.lo, kFix1);
  616.  
  617.     RectMatrix(&aMatrix, &from, &to);
  618.     SetTrackMatrix( pictT, &aMatrix );
  619.     if (store->clip) SetTrackClipRgn(pictT, store->clip);
  620.  
  621. bail:
  622.  
  623.     DisposHandle((Handle)sampleDesc);
  624.     return err;
  625. }
  626.  
  627. pascal ComponentResult SGPictGetDataRate (SGPictGlobals store, long *bytesPerSecond)
  628. {
  629.     // take a guess at our data rate
  630.     *bytesPerSecond = 24 * 1024;
  631.     if (store->bytesWritten) {
  632.         TimeValue timeNow = GetTimeBaseTime(store->base, 8, nil); // 1/8th second resolution
  633.  
  634.         if (!timeNow)
  635.             return seqGrabInfoNotAvailable;
  636.  
  637.         *bytesPerSecond = (store->bytesWritten / timeNow) * 8;  // convert back to seconds
  638.     }
  639.  
  640.     return noErr;
  641. }
  642.  
  643. /************************
  644.     SG Pict Channel
  645.     Specific Calls
  646. ************************/
  647.  
  648. pascal ComponentResult SGPictSetShowTickCount (SGPictGlobals store, Boolean show)
  649. {
  650.     store->showTickCount = show;
  651.     return noErr;
  652. }
  653.  
  654. pascal ComponentResult SGPictGetShowTickCount (SGPictGlobals store, Boolean *show)
  655. {
  656.     *show = store->showTickCount;
  657.     return noErr;
  658. }
  659.  
  660. /************************
  661.     Panel Calls
  662. ************************/
  663.  
  664. pascal ComponentResult SGPictPanelGetDitl (SGPictGlobals store, Handle *ditl)
  665. {
  666.     *ditl = GetResource('DITL', 7000); 
  667.     if (!*ditl) return resNotFound;
  668.     DetachResource(*ditl);
  669.     return noErr;
  670. }
  671.  
  672. pascal ComponentResult SGPictPanelInstall (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset)
  673. {
  674.     Rect newBounds;
  675.     short kind;
  676.     Handle h;
  677.  
  678.     // reset this channel to use the dialog window and be in preview mode with no clip
  679.     SGSetGWorld(store->self, (CGrafPtr)d, GetMainDevice());
  680.     SGGetChannelUsage(store->self, &store->saveUsage);
  681.     SGSetChannelUsage(store->self, seqGrabPreview);
  682.  
  683.     SGSetChannelClip(c, nil);
  684.  
  685.     GetDItem(d, 1 + itemOffset, &kind, &h, &newBounds);
  686.     SGSetChannelBounds(c, &newBounds);
  687.  
  688.     SGStartPreview(store->self);
  689.  
  690.     return noErr;
  691. }
  692.  
  693. pascal ComponentResult SGPictPanelEvent (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset, 
  694.             EventRecord *theEvent, short *itemHit, Boolean *handled)
  695. {
  696.     if (theEvent->what == nullEvent)
  697.         return SGIdle(store->self);
  698.  
  699.     return noErr;
  700. }
  701.  
  702. pascal ComponentResult SGPictPanelRemove (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset)
  703. {
  704.     SGStop(store->self);
  705.     SGRelease(store->self);
  706.  
  707.     // note that the clip and bounds are automatically restored for us because they were stored by us with the
  708.     //    SGGetSettings call
  709.  
  710.     SGSetChannelUsage(store->self, store->saveUsage);
  711.  
  712.     return noErr;
  713. }
  714.  
  715. pascal ComponentResult SGPictPanelGetSettings (SGPictGlobals store, SGChannel c, UserData *result, long flags)
  716. {
  717.     OSErr err = noErr;
  718.     UserData ud = 0;
  719.     MatrixRecord matrix;
  720.     RgnHandle clip;
  721.  
  722.     if (err = NewUserData(&ud)) goto bail;
  723.  
  724.     // add matrix to user data
  725.     if (SGGetChannelMatrix(c, &matrix) == noErr) {
  726.         if (err = SetUserDataItem(ud, &matrix, sizeof(matrix), sgMatrixType, 1)) goto bail;
  727.     }
  728.  
  729.     // store clip, if there is one
  730.     if (SGGetChannelClip(c, &clip) == noErr) {
  731.         if (clip)
  732.             err = AddUserData(ud, (Handle)clip, sgClipType);
  733.         else
  734.             err = SetUserDataItem(ud, nil, 0, sgClipType, 1);    // add a dummy to indicate none
  735.         DisposeRgn(clip);
  736.         if (err) goto bail;
  737.     }
  738.  
  739. bail:
  740.     if (err) {
  741.         DisposeUserData(ud);
  742.         ud = 0;
  743.     }
  744.     *result = ud;
  745.  
  746.     return err;
  747. }
  748.  
  749. pascal ComponentResult SGPictPanelSetSettings (SGPictGlobals store, SGChannel c, UserData ud, long flags)
  750. {
  751.     OSErr err;
  752.     RgnHandle clip = NewRgn();
  753.     MatrixRecord matrix;
  754.  
  755.     // restore clip, if one was stored
  756.     if (GetUserData(ud, (Handle)clip, sgClipType, 1) == noErr) {
  757.         if (err = SGSetChannelClip(c, GetHandleSize((Handle)clip) ? clip : 0)) goto bail;
  758.     }
  759.  
  760.     // restore matrix
  761.     if (err = GetUserDataItem(ud, &matrix, sizeof(matrix), sgMatrixType, 1)) goto bail;
  762.     if (err = SGSetChannelMatrix(c, &matrix)) goto bail;
  763.  
  764. bail:
  765.     DisposeRgn(clip);
  766.     return err;
  767. }
  768.  
  769.